<template>
	<div style="width: 100%;height: 100%;">
		<title-common style="margin-bottom: 10px" v-if="config.showTitle" :config="config"></title-common>
		<div :class="filter.styles.layout=='standard'?'filter-component':'filter-component filter-component-vertical'">
			<div
				:class="{ 'filter-1':paramMapping.stylize==1,'filter-2':paramMapping.stylize==2,'filter-3':paramMapping.stylize==3,'filter-4':paramMapping.stylize==4,'filter-5':paramMapping.stylize==5}"
				v-for="(paramMapping,index) in filter.advancedConf.publish.paramMapping" :key="index">
				<div
					:class="[filter.styles.layout=='standard'?'filter-component-list':'']">
					<div :style="{'color':config.styles.titleColor,'font-size':config.styles.fontSize+'px'}" :class="[filter.styles.layout=='standard'?'filter-component-list-le':'']">
						{{ paramMapping.label }}
					</div>
					<div
						:class="[filter.styles.layout=='standard'?'filter-component-list-ri':'filter-component-list-ri-vertical']">
						<a-input v-if="paramMapping.type=='text'" v-model:value="paramMapping.value"
								 @change="onChange(paramMapping)"
								 allowClear></a-input>
						<a-input type="number" v-else-if="paramMapping.type=='number'" v-model:value="paramMapping.value"
								 @change="onChange(paramMapping)"/>
						<a-select style="width: 100%" v-if="paramMapping.type=='select'"
								  :mode="paramMapping.settings.multiSelect?'multiple':'default'"
								  allowClear v-model:value="paramMapping.value"
								  @change="onChange(paramMapping)" :options="optionObj[paramMapping.key]"></a-select>
						<a-date-picker
                            :locale="locale"
							:value="getDate(paramMapping,'YYYY-MM-DD')"
							@change="dateChange($event,paramMapping,'YYYY-MM-DD')"
							v-else-if="paramMapping.type=='date'"
                            :show-time="paramMapping.settings.format!='YYYY-MM-DD'"
							:format="paramMapping.settings.format || 'YYYY-MM-DD'"
						/>
                        <a-date-picker style="width: 100%"
                                       :locale="locale"
                                       @change="dateChange($event,paramMapping,'YYYY-MM')"
                                       v-else-if="paramMapping.type=='month'"
                                       :value="getDate(paramMapping,'YYYY-MM')"
                                       picker="month" />
                        <a-date-picker style="width: 100%"
                                       :locale="locale"
                                       v-else-if="paramMapping.type=='year'"
                                       @change="dateChange($event,paramMapping,'YYYY')"
                                       :value="getDate(paramMapping,'YYYY')"
                                       picker="year" />
						<a-range-picker
                            :locale="locale"
							:value="getRangeDate(paramMapping)"
                            :show-time="paramMapping.settings.format!='YYYY-MM-DD'"
                            :format="paramMapping.settings.format || 'YYYY-MM-DD'"
							v-else-if="paramMapping.type=='dateRange'"
							@change="rangeDateChange($event,paramMapping)"
						/>
						<rx-input-button v-else-if="paramMapping.type=='dialog'"
										 @change="onChange(paramMapping)" v-model="paramMapping.value"
										 @btnClick="openDialog($event,paramMapping)"/>
                        <rx-user-component v-else-if="paramMapping.type=='user'" v-model="paramMapping.values"
                                           @change="onChange(paramMapping)" :single="!paramMapping.settings.multiSelect" :readonly="false"  style="width:100%"></rx-user-component>
                        <rx-group-component v-else-if="paramMapping.type=='group'" v-model="paramMapping.values"
                                            :single="!paramMapping.settings.multiSelect" @change="onChange(paramMapping)"></rx-group-component>
                        <rx-tree-select-ctl class="filt-tree"  v-else-if="paramMapping.type=='tree'" v-model="paramMapping.values"
                                            :multiValue="false" :labelInValue="false" :toTree="false" :multiSelect="paramMapping.settings.multiSelect"
                                            :dataSource="optionObj[paramMapping.key]" style="width: 100%"/>
					</div>
				</div>
			</div>
            <div v-if="filter.styles.showButton">
                <a-button type="primary" @click="search">
                    <template #icon>
                        <SearchOutlined />
                    </template>
                    {{filterI18n('searchBtn','查询')}}
                </a-button>
                <a-button style="margin-left: 4px" @click="reset">
                    <template #icon>
                        <RedoOutlined />
                    </template>
                    {{filterI18n('resetBtn','重置')}}
                </a-button>
            </div>
		</div>
	</div>
</template>
<script>
/**
 * 筛选器组件
 */
import ComponentView from "@/views/modules/preview/components/common/component-view.js";
import {debounce} from "lodash-es";
import screenApi from "@/api/screen-api.js";
import dayjs from "dayjs";
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
import {RxTreeSelectCtl,RxInputButton, Util} from "@lowcode/jpaas-base-lib";
import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';
import {RxUserComponent,RxGroupComponent,ShareDialog} from "@lowcode/jpaas-share-component"
export default {
	name: "filter-view",
	mixins: [ComponentView],
	components: {
		RxUserComponent,
		RxTreeSelectCtl,
		RxGroupComponent,
        RxInputButton
	},
	data() {
		return {
			//筛选器
			filter: {},
			//下拉框数据
			optionObj: {},
            locale
		}
	},
	created() {
		this.getData();
	},
	methods: {
		filterI18n(name,text,key){
			return this.$ti18(name,text,"filterLang",key);
		},
		getData() {
			this.filter = JSON.parse(JSON.stringify(this.config));
			this.initOptions();
		},
		//构建参数并触发事件
		initParamMapping(reset) {
			if(!this.filter || !this.filter.advancedConf || !this.filter.advancedConf.publish){
				return;
			}
			let paramMappings = this.filter.advancedConf.publish.paramMapping;
			let params = {};
			for (let i = 0; i < paramMappings.length; i++) {
				let paramMapping = paramMappings[i];
				if (reset) {
					paramMapping.value = "";
                    paramMapping.values = "";
                    if(paramMapping.type=='select'){
                        paramMapping.value =paramMapping.settings.multiSelect? []:'';
                    }
				}else if ((paramMapping.type == 'user' || paramMapping.type == 'group') && paramMapping.values) {
					let ary = [];
					for (let i = 0; i < paramMapping.values.length; i++) {
						ary.push(paramMapping.values[i].id);
					}
					paramMapping.value = ary.join(",");
				} else if (paramMapping.type == 'tree') {
					if(paramMapping.settings && paramMapping.settings.multiSelect){
						paramMapping.value = paramMapping.values.join(",");
					}else {
						paramMapping.value = paramMapping.values;
					}
				}
				params[paramMapping.key] = paramMapping.value || "";
			}
			//触发事件
			this.handEvent(params);
		},
		onChange: debounce(function (paramMapping) {
			//查找下拉框是否配置当前为参数
			this.findSelectParams(paramMapping);
			//未配置按钮则直接触发事件
			if (!this.filter.styles.showButton) {
				this.initParamMapping(false);
			}
		}, 500),
		//触发事件
		handEvent(params) {
			this.$bus.emit("filterEvent", {component: this.config.key, params: params});
		},
		search() {
			this.initParamMapping(false);
		},
		reset() {
			this.initParamMapping(true);
		},
		initOptions() {
			//下拉框获取选项数据
			for (let i = 0; i < this.filter.advancedConf.publish.paramMapping.length; i++) {
				let paramMapping = this.filter.advancedConf.publish.paramMapping[i];
				if (paramMapping.settings && (paramMapping.type == "select" || paramMapping.type == "tree")) {
					this.getOptions(paramMapping.settings, paramMapping.key, "", paramMapping.type);
				}
			}
		},
		getOptions(settings, key, params, type) {
			if (!settings) {
				return;
			}
			let options = [];
			//自定义
			if (settings.from == "self") {
				let dataSource = settings.dataSource;
				for (let j = 0; j < dataSource.length; j++) {
					options.push({
						value: dataSource[j].key,
						label: dataSource[j].name,
					})
				}
                this.optionObj[key]=options;
			}
			//数据字典
			else if (settings.from == "dic") {
                screenApi.loadDicByPidAndDicId(settings.dicKey, "").then(res => {
					if (res.length && res.length > 0) {
						for (let j = 0; j < res.length; j++) {
							options.push({
								id: res[j].pkId,
								value: res[j].value,
								label: res[j].name,
								parentId: res[j].parentId,
							})
						}
					}
					if (type == 'tree') {
						options = Util.listToTree(options, "id", "parentId");
					}
                    this.optionObj[key]=options;
				});
			}
			//sql
			else if (settings.from == "sql") {
				if (!settings.sql) {
					return;
				}
				let textfield = settings.sql_textfield;
				let valuefield = settings.sql_valuefield;
				let parentfield = settings.sql_parentfield;
				let sql = JSON.parse(settings.sql).value;
                screenApi.queryForJson(sql, {params: params}).then(res => {
					let data = res.data;
					if (data.length && data.length > 0) {
						for (let j = 0; j < data.length; j++) {
							options.push({
								value: data[j][valuefield],
								label: data[j][textfield],
								parentId: data[j][parentfield],
							})
						}
					}
					if (type == 'tree') {
						options = Util.listToTree(options, "value", "parentId");
					}
                    this.optionObj[key]=options;
				});
			}
			//权限数据
			else if (settings.from == "grant") {
				if (settings.grant) {
					let grant = JSON.parse(settings.grant).value;
                    screenApi.loadByGrant(grant).then(res => {
						for (let j = 0; j < res.data.length; j++) {
							options.push({
								value: res.data[j]["value"],
								label: res.data[j]["label"],
								parentId: res.data[j]["parentId"]
							})
						}
						if (type == 'tree') {
							options = Util.listToTree(options, "value", "parentId");
						}
                        this.optionObj[key]=options;
					})
				}
			}
		},
		//查找下拉框是否配置当前为参数
		findSelectParams(paramMapping) {
			for (let i = 0; i < this.filter.advancedConf.publish.paramMapping.length; i++) {
				let mapping = this.filter.advancedConf.publish.paramMapping[i];
				//下拉框 自定义查询
				if ((mapping.type == "select" || mapping.type == "tree") && mapping.settings.from == 'sql') {
					for (let j = 0; j < mapping.settings.paramsData.length; j++) {
						let paramsData = mapping.settings.paramsData[j];
						if (paramMapping.key == paramsData.bindVal) {
							let params = {};
							params[paramsData.fieldName] = paramMapping.value;
							this.getOptions(mapping.settings, mapping.key, JSON.stringify(params), mapping.type);
						}
					}
				}
			}
		},
		dateChange(value, paramMapping,format) {
            if(!value){
                paramMapping.value = "";
            }else {
                paramMapping.value = dayjs(value).format(paramMapping.settings.format || format);
            }
            if (!this.filter.styles.showButton) {
                this.initParamMapping(false);
            }
		},
		rangeDateChange(values, paramMapping) {
			if(!values || values.length==0){
				paramMapping.value = "";
				return;
			}
			let ary = [];
			ary.push(dayjs(values[0]).format(paramMapping.settings.format || 'YYYY-MM-DD'));
			ary.push(dayjs(values[1]).format(paramMapping.settings.format || 'YYYY-MM-DD'));
			paramMapping.value = ary;
		},
		openDialog(vm, paramMapping) {
			let settings = paramMapping.settings;
			let dialog = settings.dialog;
			let valueField = settings.valueField;
			let textField = settings.textField;
			let single = !settings.multiSelect;
			if (!dialog) {
				this.$message.error(this.filterI18n('configDialog','请配置对话框!'));
				return;
			}
			let dialogKey = JSON.parse(dialog).value;
            let parameter = {
                key:dialogKey,
                single:single,
            };
            ShareDialog.dialog(parameter, {curVm: this, zIndex:9999}, function (data) {
				if (data.rows.length == 0) {
					return;
				}
				let values = [];
				let texts = [];
				//多选
				if (data.multiSelect) {
					for (let i = 0; i < data.rows.length; i++) {
						values.push(data.rows[i][valueField]);
						texts.push(data.rows[i][textField]);
					}
				} else {
					values.push(data.rows[0][valueField]);
					texts.push(data.rows[0][textField]);
				}
				vm.setVal(values.join(','), texts.join(','));
				paramMapping.value = values.join(',');
			});
		},
		getDate(paramMapping,format){
			if(!paramMapping.value){
				return "";
			}

			let date=dayjs(paramMapping.value,paramMapping.settings.format|| format ||'YYYY-MM-DD');
			return  date || "";
		},

		getRangeDate(paramMapping){
			if(!paramMapping.value){
				return "";
			}
			let ary = [];
			ary.push(dayjs(paramMapping.value[0],paramMapping.settings.format||'YYYY-MM-DD'));
			ary.push(dayjs(paramMapping.value[1],paramMapping.settings.format||'YYYY-MM-DD'));
			return  ary || "";
		}
	},
	watch: {
		config: {
			handler: function (val, oldVal) {
				if (val) {
					this.getData();
				}
			},
			deep: true
		}
	}
}
</script>

<style lang="less">
.filter-component{
	.rx-tags li{
		background-color: rgba(66, 133, 244, 0.6) !important;
		color: white!important;
	}
	.rx-tags li .anticon{
		color: rgba(255,255,255,0.5);
	}
	.ant-select-selection__clear{
		background-color: rgba(0, 0, 0, 0) !important;
		color: white;
	}
	.ant-input-clear-icon{
		color: white;
	}
	.rx-textBoxList-iconBox:hover{
		color: white;
	}
    .rx-tags{
        height: 32px;
    }
    .rx-textBoxList-container{
        border-radius: 6px;
    }
    .ant-input-group-addon{
        background: white;
    }
}
.filter-component{
	.inputBtnBox {
		margin-top: 0px !important;
	}
	.ant-select-tree {
		max-height: 400px !important;
		overflow: auto;
		margin-top: 10px;
	}
}

.filter-component-list-ri-vertical {
	margin-top: 8px;
	margin-right: 10px;
}

.filter-component-list {
	display: flex;
	align-items: center;
}

.filter-component-list-le {
	text-align: right;
	margin-right: 15px
}

.filter-component-list-ri {
	flex: 1;
	margin-right: 15px;
}

.filter-component {
	display: flex;
	flex-wrap: wrap;
    gap: 15px 0px;
}

.filter-1 {
	flex: 0 0 25% !important;
}

.filter-2 {
	flex: 0 0 33.33% !important;
}

.filter-3 {
	flex: 0 0 66.66% !important;
}

.filter-4 {
	flex: 0 0 50% !important;
}
.filter-5{
	flex: 0 0 100% !important;
}
.filter-component-vertical{
    align-items: flex-end;
}
</style>
